<template>
  <div class="c-table">
    <el-table
      :data="rows"
      border
      ref="cTable"
      style="width: 100%"
      :show-summary="isShowSum"
      :summary-method="isShowSum ? getSummaries : null"
      tooltip-effect="light"
      @selection-change="handleSelectionChange"
      @sort-change="handleSortChange"
      v-bind="$attrs"
      v-on="$listeners"
    >
      <el-table-column
        type="index"
        width="55"
        align="center"
        label="序号"
        :index="indexMethod"
        v-if="isShowIndex"
      />
      <el-table-column
        v-if="isShowSelection === 'checkbox'"
        type="selection"
        align="center"
        :selectable="canBeSelect"
        width="55"
      />
      <el-table-column
        v-if="isShowSelection === 'switch'"
        type="switch"
        align="center"
        width="120"
      >
        <template #default="scope">
          <div>
            <!-- :disabled="scope.row.isCheck" -->
            <el-switch
              @change="handleSwitchChange(scope.row)"
              v-model="scope.row.isCheck"
              active-text="是"
              inactive-text="否"
            >
            </el-switch>
          </div>
        </template>
      </el-table-column>
      <template v-for="item in columns">
        <el-table-column
          :show-overflow-tooltip="!item.template"
          v-if="!item.hide"
          :prop="item.prop"
          :label="item.name"
          :width="item.width ? item.width : ''"
          :fixed="item.fixed || false"
          :key="item.name"
          :align="item.align || 'left'"
          :sortable="item.sort ? 'custom' : false"
        >
          <template #default="scope">
            <slot :name="item.prop" :data="scope.row">
              <div v-if="!item.template" class="c-copy">
                <span class="c-copy-text">{{
                  formatterValue(scope.row[item.prop], item.type)
                }}</span>
                <i
                  class="el-icon-document-copy c-copy-icon"
                  @click="handleCopy(scope.row[item.prop])"
                ></i>
              </div>
              <div v-else>
                <!-- v-hasPermi="ctx.hasPermi" -->
                <el-button
                  type="text"
                  v-for="(ctx, ind) in item.template.btn"
                  :key="ind"
                  :icon="ctx.icon"
                  @click="handleEvent(ctx.event, scope.row)"
                  >{{ ctx.label }}</el-button
                >
              </div>
            </slot>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <div class="c-table-footer">
      <slot name="footer"> <span></span></slot>
      <el-pagination
        v-show="rows && rows.length && isShowPagination"
        :current-page="pageConfig.pageNum"
        @current-change="handleCurrentChange"
        @size-change="handleSizeChange"
        :page-sizes="pageSizes"
        :pager-count="5"
        :page-size="pageConfig.pageSize"
        :layout="layout"
        :total="pageConfig.total"
        background
      ></el-pagination>
    </div>
  </div>
</template>

<script>
export default {
  name: 'CTable',
  components: {},
  mixins: [],
  props: {
    // 表格列配置数据
    columns: {
      type: Array,
      default: () => [],
    },
    // 表格数据
    rows: {
      type: Array,
      default: () => [],
    },
    // 分页配置
    pageConfig: {
      type: Object,
      default: () => {
        return {
          pageNum: 1,
          pageSize: 10,
          total: 0,
        }
      },
    },
    // 是否显示分页
    isShowPagination: {
      type: Boolean,
      default: true,
    },
    // 分页控制器
    layout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper',
    },
    // 分页大小
    pageSizes: {
      type: Array,
      default: () => [10, 20, 50, 100],
    },
    // 是否显示序号
    isShowIndex: {
      type: Boolean,
      default: true,
    },
    // 是否显示选择框 checkbox复选框 switch开关
    isShowSelection: {
      type: String,
      default: 'checkbox',
    },
    // 是否显示合计
    isShowSum: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {}
  },
  computed: {},
  watch: {},
  filter: {},
  created() {},
  mounted() {
    this.toggleSelection()
  },
  methods: {
    // switch开关
    handleSwitchChange(row) {
      this.$emit('handleSwitchChange', row)
    },
    // 初始化禁用不可选中
    canBeSelect(row) {
      if (!row.isCheck) return false
      return true
    },
    // 初始化默认选中状态
    toggleSelection(rows) {
      if (rows) {
        rows.forEach((row) => {
          this.$refs.cTable.toggleRowSelection(row)
        })
      } else {
        this.$refs.cTable.clearSelection()
      }
    },
    // 日期格式化 这个若依有
    parseTime(time, pattern) {
      if (arguments.length === 0 || !time) {
        return null
      }
      const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
      let date
      if (typeof time === 'object') {
        date = time
      } else {
        if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
          time = parseInt(time)
        } else if (typeof time === 'string') {
          time = time
            .replace(new RegExp(/-/gm), '/')
            .replace('T', ' ')
            .replace(new RegExp(/\.[\d]{3}/gm), '')
        }
        if (typeof time === 'number' && time.toString().length === 10) {
          time = time * 1000
        }
        date = new Date(time)
      }
      const formatObj = {
        y: date.getFullYear(),
        m: date.getMonth() + 1,
        d: date.getDate(),
        h: date.getHours(),
        i: date.getMinutes(),
        s: date.getSeconds(),
        a: date.getDay(),
      }
      const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
        let value = formatObj[key]
        if (key === 'a') {
          return ['日', '一', '二', '三', '四', '五', '六'][value]
        }
        if (result.length > 0 && value < 10) {
          value = '0' + value
        }
        return value || 0
      })
      return time_str
    },
    // 索引
    indexMethod(index) {
      return (
        this.pageConfig.pageSize * (this.pageConfig.pageNum - 1) + index + 1
      )
    },
    /**
     * 计算合计
     */
    getSummaries(param) {
      const { columns, data } = param
      const sums = []
      columns.forEach((column, index) => {
        const values = data.map((item) => Number(item[column.property]))
        if (
          this.columns.findIndex(
            (ctx) => ctx.amount && ctx.prop === column.property
          ) !== -1 &&
          !values.every((value) => isNaN(value))
        ) {
          sums[index] = values.reduce((prev, curr) => {
            const value = Number(curr)
            if (!isNaN(value)) {
              return prev + curr
            } else {
              return prev
            }
          }, 0)
          sums[index] += ''
        } else {
          sums[index] = ''
        }
      })
      if (this.isShowIndex || this.isShowSelection) {
        sums[0] = '合计'
      }
      return sums
    },
    /**
     * 排序
     * @param {Object} param
     * @param {String} param.prop: 排序字段
     * @param {String} param.order: 排序方式 ascending 升序 descending 降序
     */
    handleSortChange({ prop, order }) {
      this.$emit('handleSortChange', { prop, order })
    },
    // 多选操作
    handleSelectionChange(val) {
      this.$emit('handleSelectionChange', val)
    },
    // 分页大小
    handleSizeChange(pageSize) {
      this.$emit('handleSizeChange', pageSize)
    },
    // 当前页
    handleCurrentChange(pageNum) {
      this.$emit('handleCurrentChange', pageNum)
    },
    // 复制当前文本
    handleCopy(val) {
      try {
        navigator.clipboard.writeText(val)
      } catch (error) {
        // 复制当前文本失败 降级使用剪切板
        const textarea = document.createElement('textarea')
        textarea.value = val
        document.body.appendChild(textarea)
        textarea.select()
        document.execCommand('copy')
        document.body.removeChild(textarea)
      }
    },
    /**
     * 格式化内容
     * @param value
     * @param type
     * @returns {*}
     */
    formatterValue(value, type) {
      switch (type) {
        case 'date':
          return this.parseTime(value)
        case 'number':
          return Number(value).toLocaleString()
        default:
          return value
      }
    },
    /**
     * 操作按钮
     * @param event 触发事件名
     * @param rowData 当前行数据
     */
    handleEvent(event, rowData) {
      this.$emit(event, rowData)
    },
  },
}
</script>
<style lang="scss" scoped>
.c-copy {
  cursor: pointer;
  display: flex;
  align-items: center;
  &-text {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  &-icon {
    display: none;
  }
  &:hover {
    flex: 1;
    .c-copy-icon {
      width: 14px;
      display: block;
    }
  }
}
.c-table-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 20px;
}
::v-deep .el-tooltip__popper {
  border: none !important;
}
</style>
